/*
Copyright (c) 2008,2009, David Beck

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

1. Redistributions of source code must retain the above copyright
   notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
   notice, this list of conditions and the following disclaimer in the
   documentation and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#ifndef _rt0d4_rx_h_included_
#define _rt0d4_rx_h_included_

/**
   @file rt0d4_rx.h
   @brief Users of the rt0d4 Rx security model are expected to call these functions
*/
#define RT0D4_WINDOWS_H_INCLUDED

#include "common.h"
#include "validate_cb.h"
#include "conn_cb.h"

#ifdef __cplusplus
extern "C" {
#endif /*__cplusplus*/
  #include <rx/rx.h>
  #include "rt0d4_rx_err.h"
#ifdef __cplusplus
}
#endif /*__cplusplus*/

/*********************************/
/* common for client and server */
/*********************************/

/**
    @brief Replaces the default EC algorithms used (optional)
    @see rt0d4::sec::ecdh_pkt

    For the default values @see rt0d4_rx_algs_subset_default

    Optionally called by the client and the server.The default values
    are suitable for most situations, so it is not mandatory to call
    this function.
*/
RT0D4_CDECL
int rt0d4_rx_AddAlgorithms(
                struct rx_securityClass * sec_obj,
                const char ** algs);

/**
    @brief Sets the minimum and maximum EC key strength to be used (optional)
    @see rt0d4::sec::ecdh_pkt

    The default value for min_strength is 192 EC bits.
    The default value for max_strength is 521 EC bits.

    Optionally called by the client or the server.The default values
    are suitable for most situations, so it is not mandatory to call
    this function.
*/
RT0D4_CDECL
int rt0d4_rx_SetEcKeyStrength(
                struct rx_securityClass * sec_obj,
                int min_strength,
                int max_strength);

/**
    @brief Sets own certificate (optional)
    @see rt0d4::sec::ecdh_pkt

    The given certificate will be transfered as part of the challenge or
    response packet. The content of the certificate is uninterpreted. It
    should be checked by the related peer callback (to be set by
    rt0d4_rx_SetPeerCertValidateCallBack)

    Optionally called by the client and the server.
*/
RT0D4_CDECL
int rt0d4_rx_SetOwnCert(
                struct rx_securityClass * sec_obj,
                const unsigned char * cert,
                size_t len);

/**
    @brief Sets the certificate verification callback (optional)
    @param cb is the callback function to be called to verify the certificate
    @see validate_peer_cert in validate_cb.h

    Optionally called by the client and the server.

    This function delegates the responsibility of checking the
    peer cert to cb. If no function is provided then the peer certificate
    will not be checked.

    The cb should return 0 on success and any other value on failure.
*/
RT0D4_CDECL
int rt0d4_rx_SetPeerCertValidateCallBack(
                struct rx_securityClass * sec_obj,
                validate_peer_cert cb);


/*********************************/
/* client only functions         */
/*********************************/
/**
    @brief Creates a new client security object (mandatory)

    The result of this function will be passed to rx_NewConnection().
    Before passing it, one may want to set optional parameters using:

    @li rt0d4_rx_AddAlgorithms()
    @li rt0d4_rx_SetEcKeyStrength()
    @li rt0d4_rx_SetPeerCertValidateCallBack()
    @li rt0d4_rx_SetOwnCert()
    @li rt0d4_rx_SetOwnCredentials()

    All of them are optional.

    Must be called by the client.
*/
RT0D4_CDECL
struct rx_securityClass * rt0d4_rx_NewClientSecurityObject(void);

/**
    @brief Destroy client security object (recommended)

    The result of this function will be passed to rx_NewConnection().
    Before passing it, one may want to set optional parameters using:

    Must be called by the client.
*/
RT0D4_CDECL
void rt0d4_rx_DestroyClientSecurityObject(struct rx_securityClass * sec);


/**
    @brief Sets own credentials (optional)
    @see rt0d4::sec::ecdh_pkt

    The credentials will be sent with the response packet generated.
    The credentials travel on the network in encrypted form. The server will check
    the credentials if the corresponding callback is set on the server side.

    Optionally called by the client.
*/
RT0D4_CDECL
int rt0d4_rx_SetOwnCredentials(
                struct rx_securityClass * sec_obj,
                const char * login,
                const char * password);

/*********************************/
/* server only functions         */
/*********************************/

/**
    @brief Creates a new server security object (mandatory)

    The result of this function will be passed to rx_NewService().
    Before passing it, one may want to set optional parameters using:

    @li rt0d4_rx_AddAlgorithms()
    @li rt0d4_rx_SetEcKeyStrength()
    @li rt0d4_rx_SetPeerCertValidateCallBack()
    @li rt0d4_rx_SetPeerCredentialsValidateCallBack()
    @li rt0d4_rx_SetConnDataCreateCallBack()
    @li rt0d4_rx_SetConnDataDestroyCallBack()
    @li rt0d4_rx_SetOwnCert()

    All of them are optional.

    Must be called by the client.
*/
RT0D4_CDECL
struct rx_securityClass * rt0d4_rx_NewServerSecurityObject(void);

/**
    @brief Sets the credential verification callback (optional)
    @param sec_obj is the structure created by rt0d4_rx_NewServerSecurityObject
    @param cb is the callback function to be called to verify the credentials
    @see validate_peer_credentials in validate_cb.h

    Optionally called by the the server.

    This function delegates the responsibility of checking the
    peer credentials to cb. If no callback was set, then the peer credential
    will not be validated.

    The cb should return 0 on success and any other value on failure.
*/
RT0D4_CDECL
int rt0d4_rx_SetPeerCredentialsValidateCallBack(
                struct rx_securityClass * sec_obj,
                validate_peer_credentials cb);

/**
    @brief Sets a callback that may create private data related to a specific connection (optional)
    @param sec_obj is the structure created by rt0d4_rx_NewServerSecurityObject
    @param cb is the callback that creates the connection data
    @see create_conn_data in conn_cb.h

    This function is called once when the connection is authenticated and
    established. The idea behind is, the callback function receives the
    username, password and the certificate. Then it creates a private
    structure that stores data for the given connection. The data may be 
    retrived on demand.

    This is an alternative to the rt0d4_rx_SetConnData function.
    If both are used the rt0d4_rx_SetConnData may overwrite the data created
    depending on the actual order.

*/
RT0D4_CDECL
int rt0d4_rx_SetConnDataCreateCallBack(
                struct rx_securityClass * sec_obj,
                create_conn_data cb);

/**
    @brief Sets a callback that destroys the connection related private data (optional)
    @param sec_obj is the structure created by rt0d4_rx_NewServerSecurityObject
    @param cb is the callback that destroys the connection data
    @see destroy_conn_data in conn_cb.h

    This function works in concert with the create_conn_data callback.
    It destroys the connection related private data when the internal
    connection callback routine runs.

    The callback will run either on the data created by the create_conn_data callback
    or the pointer supplied by rt0d4_rx_SetConnData.

*/
RT0D4_CDECL
int rt0d4_rx_SetConnDataDestroyCallBack(
                struct rx_securityClass * sec_obj,
                destroy_conn_data cb);

/**
    @brief Sets connection specific data (optional)
    @param acall is the call structure as supplied by Rx
    @param data is a pointer to an opaque structure to be associated with the connection
 
    Ties a pointer to a user specified data structure to the connection. This
    library does not interpret the content of the data structure. It is treated
    as opaque data. This updates the same data as the create_conn_data callback
    so care must be taken.
 
    The data may be freed automatically by the callback function supplied to the
    rt0d4_rx_SetConnDataDestroyCallBack function.
 
    The callback is called when Rx detects the connection is terminated.
*/
RT0D4_CDECL
int rt0d4_rx_SetConnData(
                struct rx_call * acall,
                void * data);

/**
    @brief Retrieves the connection specific data (optional)
    @param acall is the call structure as supplied by Rx
    
    The return value of this function is the connection related data structure as
    created by the create_conn_data callback or set by the rt0d4_rx_SetConnData
    function.
*/
RT0D4_CDECL
void * rt0d4_rx_GetConnData(
                struct rx_call * acall);

/**
    @brief Retrieves the username associated with the connection (optional)
    @param acall is the call structure as supplied by Rx
 
    The client supplied username can be retrieved here.
    Only make sense on the server side.
*/
RT0D4_CDECL
const char * rt0d4_rx_GetConnLogin(
                struct rx_call * acall);

/**
    @brief Retrieves the password associated with the connection (optional)
    @param acall is the call structure as supplied by Rx
 
    The client supplied password can be retrieved by this function.
    Only make sense on the server side.
*/
RT0D4_CDECL
const char * rt0d4_rx_GetConnPassword(
                struct rx_call * acall);

/**
    @brief Retrieves the certificate associated with the connection (optional)
    @param acall is the call structure as supplied by Rx
    @param len is a reference to the length of the certificate (OUTPUT)

    The client supplied certificate data can be retrived by this function
    Only make sense on the server side.
*/
RT0D4_CDECL
const unsigned char * rt0d4_rx_GetConnCert(
                struct rx_call * acall,
                size_t * len);

#endif /* _rt0d4_rx_h_included_ */
